<?php
/*
 * @ https://EasyToYou.eu - IonCube v11 Decoder Online
 * @ PHP 7.2 & 7.3
 * @ Decoder version: 1.1.6
 * @ Release: 10/08/2022
 */

// Decoded file for php version 71.
function isTrusted($alipayCert, $rootCert)
{
    $alipayCerts = readPemCertChain($alipayCert);
    $rootCerts = readPemCertChain($rootCert);
    if(verifyCertChain($alipayCerts, $rootCerts)) {
        return verifySignature($alipayCert, $rootCert);
    }
    return false;
}
function verifySignature($alipayCert, $rootCert)
{
    $alipayCertArray = explode("-----END CERTIFICATE-----", $alipayCert);
    $rootCertArray = explode("-----END CERTIFICATE-----", $rootCert);
    $length = count($rootCertArray) - 1;
    $checkSign = isCertSigner($alipayCertArray[0] . "-----END CERTIFICATE-----", $alipayCertArray[1] . "-----END CERTIFICATE-----");
    if(!$checkSign) {
        $checkSign = isCertSigner($alipayCertArray[1] . "-----END CERTIFICATE-----", $alipayCertArray[0] . "-----END CERTIFICATE-----");
        if($checkSign) {
            $issuer = openssl_x509_parse($alipayCertArray[0] . "-----END CERTIFICATE-----")["issuer"];
            for ($i = 0; $i < $length; $i++) {
                $subject = openssl_x509_parse($rootCertArray[$i] . "-----END CERTIFICATE-----")["subject"];
                if($issuer == $subject) {
                    isCertSigner($alipayCertArray[0] . "-----END CERTIFICATE-----", $rootCertArray[$i] . $rootCertArray);
                    return $checkSign;
                }
            }
        } else {
            return $checkSign;
        }
    } else {
        $issuer = openssl_x509_parse($alipayCertArray[1] . "-----END CERTIFICATE-----")["issuer"];
        for ($i = 0; $i < $length; $i++) {
            $subject = openssl_x509_parse($rootCertArray[$i] . "-----END CERTIFICATE-----")["subject"];
            if($issuer == $subject) {
                $checkSign = isCertSigner($alipayCertArray[1] . "-----END CERTIFICATE-----", $rootCertArray[$i] . "-----END CERTIFICATE-----");
                return $checkSign;
            }
        }
        return $checkSign;
    }
}
function readPemCertChain($cert)
{
    $array = explode("-----END CERTIFICATE-----", $cert);
    $certs[] = NULL;
    for ($i = 0; $i < count($array) - 1; $i++) {
        $certs[$i] = openssl_x509_parse($array[$i] . "-----END CERTIFICATE-----");
    }
    return $certs;
}
function verifyCert($prev, $rootCerts)
{
    $nowTime = time();
    if($nowTime < $prev["validFrom_time_t"]) {
        echo "证书未激活";
        return false;
    }
    if($prev["validTo_time_t"] < $nowTime) {
        echo "证书已经过期";
        return false;
    }
    $subjectMap = NULL;
    for ($i = 0; $i < count($rootCerts); $i++) {
        $subjectDN = array2string($rootCerts[$i]["subject"]);
        $subjectMap[$subjectDN] = $rootCerts[$i];
    }
    $issuerDN = array2string($prev["issuer"]);
    if(!array_key_exists($issuerDN, $subjectMap)) {
        echo "证书链验证失败";
        return false;
    }
    return true;
}
function verifyCertChain($alipayCerts, $rootCerts)
{
    $sorted = sortByDn($alipayCerts);
    if(!$sorted) {
        echo "证书链验证失败：不是完整的证书链";
        return false;
    }
    $prev = $alipayCerts[0];
    $firstOK = verifycert($prev, $rootCerts);
    $length = count($alipayCerts);
    if(!$firstOK || $length == 1) {
        return $firstOK;
    }
    $nowTime = time();
    for ($i = 1; $i < $length; $i++) {
        $cert = $alipayCerts[$i];
        if($nowTime < $cert["validFrom_time_t"]) {
            echo "证书未激活";
            return false;
        }
        if($cert["validTo_time_t"] < $nowTime) {
            echo "证书已经过期";
            return false;
        }
    }
    return true;
}
function sortByDn(&$certs)
{
    $hasSelfSignedCert = false;
    $subjectMap = NULL;
    $issuerMap = NULL;
    for ($i = 0; $i < count($certs); $i++) {
        if(isSelfSigned($certs[$i])) {
            if($hasSelfSignedCert) {
                return false;
            }
            $hasSelfSignedCert = true;
        }
        $subjectDN = array2string($certs[$i]["subject"]);
        $issuerDN = array2string($certs[$i]["issuer"]);
        $subjectMap[$subjectDN] = $certs[$i];
        $issuerMap[$issuerDN] = $certs[$i];
    }
    $certChain = NULL;
    addressingUp($subjectMap, $certChain, $certs[0]);
    addressingDown($issuerMap, $certChain, $certs[0]);
    if(count($certs) != count($certChain)) {
        return false;
    }
    for ($i = 0; $i < count($certs); $i++) {
        $certs[$i] = $certChain[count($certs) - $i - 1];
    }
    return true;
}
function isSelfSigned($cert)
{
    $subjectDN = array2string($cert["subject"]);
    $issuerDN = array2string($cert["issuer"]);
    return $subjectDN == $issuerDN;
}
function array2string($array)
{
    $string = [];
    if($array && is_array($array)) {
        foreach ($array as $key => $value) {
            $string[] = $key . "=" . $value;
        }
    }
    return implode(",", $string);
}
function addressingUp($subjectMap, &$certChain, $current)
{
    $certChain[] = $current;
    if(isselfsigned($current)) {
        return NULL;
    }
    $issuerDN = array2string($current["issuer"]);
    if(!array_key_exists($issuerDN, $subjectMap)) {
        return NULL;
    }
    addressingUp($subjectMap, $certChain, $subjectMap[$issuerDN]);
}
function addressingDown($issuerMap, &$certChain, $current)
{
    $subjectDN = array2string($current["subject"]);
    if(!array_key_exists($subjectDN, $issuerMap)) {
        return $certChain;
    }
    $certChain[] = $issuerMap[$subjectDN];
    addressingDown($issuerMap, $certChain, $issuerMap[$subjectDN]);
}
function extractSignature($der = false)
{
    if(strlen($der) < 5) {
        return false;
    }
    $der = substr($der, 4);
    while (1 < strlen($der)) {
        $class = ord($der[0]);
        $classHex = dechex($class);
        switch ($class) {
            case 3:
                $len = ord($der[1]);
                $bytes = 0;
                if($len & 128) {
                    $bytes = $len & 15;
                    $len = 0;
                    for ($i = 0; $i < $bytes; $i++) {
                        $len = $len << 8 | ord($der[$i + 2]);
                    }
                }
                return substr($der, 3 + $bytes, $len);
                break;
            case 48:
                $len = ord($der[1]);
                $bytes = 0;
                if($len & 128) {
                    $bytes = $len & 15;
                    $len = 0;
                    for ($i = 0; $i < $bytes; $i++) {
                        $len = $len << 8 | ord($der[$i + 2]);
                    }
                }
                $contents = substr($der, 2 + $bytes, $len);
                $der = substr($der, 2 + $bytes + $len);
                break;
            default:
                return false;
        }
    }
    return false;
}
function getSignatureAlgorithmOid($der = NULL)
{
    if(!is_string($der) || strlen($der) < 5) {
        return false;
    }
    $bit_seq1 = 0;
    $bit_seq2 = 2;
    $bit_oid = 4;
    if(ord($der[$bit_seq1]) !== 48) {
        exit("Invalid DER passed to getSignatureAlgorithmOid()");
    }
    if(ord($der[$bit_seq2]) !== 48) {
        exit("Invalid DER passed to getSignatureAlgorithmOid()");
    }
    if(ord($der[$bit_oid]) !== 6) {
        exit("Invalid DER passed to getSignatureAlgorithmOid");
    }
    $der = substr($der, $bit_oid);
    $len = ord($der[1]);
    $bytes = 0;
    if($len & 128) {
        $bytes = $len & 15;
        $len = 0;
        for ($i = 0; $i < $bytes; $i++) {
            $len = $len << 8 | ord($der[$i + 2]);
        }
    }
    $oid_data = substr($der, 2 + $bytes, $len);
    $oid = floor(ord($oid_data[0]) / 40);
    $oid .= "." . ord($oid_data[0]) % 40;
    $value = 0;
    for ($i = 1; $i < strlen($oid_data); $i++) {
        $value = $value << 7;
        $value = $value | ord($oid_data[$i]) & 127;
        if(!(ord($oid_data[$i]) & 128)) {
            $oid .= "." . $value;
            $value = 0;
        }
    }
    return $oid;
}
function getSignatureHash($der = NULL)
{
    if(!is_string($der) || strlen($der) < 5) {
        return false;
    }
    if(ord($der[0]) !== 48) {
        exit("Invalid DER passed to getSignatureHash()");
    }
    $der = substr($der, 2);
    if(ord($der[0]) !== 48) {
        exit("Invalid DER passed to getSignatureHash()");
    }
    $len = ord($der[1]);
    $bytes = 0;
    if($len & 128) {
        $bytes = $len & 15;
        $len = 0;
        for ($i = 0; $i < $bytes; $i++) {
            $len = $len << 8 | ord($der[$i + 2]);
        }
    }
    $der = substr($der, 2 + $bytes + $len);
    if(ord($der[0]) !== 4) {
        exit("Invalid DER passed to getSignatureHash()");
    }
    $len = ord($der[1]);
    $bytes = 0;
    if($len & 128) {
        $bytes = $len & 15;
        $len = 0;
        for ($i = 0; $i < $bytes; $i++) {
            $len = $len << 8 | ord($der[$i + 2]);
        }
    }
    return bin2hex(substr($der, 2 + $bytes, $len));
}
function isCertSigner($certPem = NULL, $caCertPem = NULL)
{
    if(!function_exists("openssl_pkey_get_public")) {
        exit("Need the openssl_pkey_get_public() function.");
    }
    if(!function_exists("openssl_public_decrypt")) {
        exit("Need the openssl_public_decrypt() function.");
    }
    if(!function_exists("hash")) {
        exit("Need the php hash() function.");
    }
    if(empty($certPem) || empty($caCertPem)) {
        return false;
    }
    $certDer = pemToDer($certPem);
    if(!is_string($certDer)) {
        exit("invalid certPem");
    }
    $encryptedSig = extractsignature($certDer);
    if(!is_string($encryptedSig)) {
        exit("Failed to extract encrypted signature from certPem.");
    }
    $pubKey = openssl_pkey_get_public($caCertPem);
    if($pubKey === false) {
        exit("Failed to extract the public key from the ca cert.");
    }
    $rc = openssl_public_decrypt($encryptedSig, $decryptedSig, $pubKey);
    if($rc === false) {
        return false;
    }
    $origCert = stripSignerAsn($certDer);
    if($origCert === false) {
        exit("Failed to extract unsigned cert.");
    }
    $oid = getsignaturealgorithmoid($decryptedSig);
    if($oid === false) {
        exit("Failed to determine the signature algorithm.");
    }
    switch ($oid) {
        case "1.2.840.113549.2.2":
            $algo = "md2";
            break;
        case "1.2.840.113549.2.4":
            $algo = "md4";
            break;
        case "1.2.840.113549.2.5":
            $algo = "md5";
            break;
        case "1.3.14.3.2.18":
            $algo = "sha";
            break;
        case "1.3.14.3.2.26":
            $algo = "sha1";
            break;
        case "2.16.840.1.101.3.4.2.1":
            $algo = "sha256";
            break;
        case "2.16.840.1.101.3.4.2.2":
            $algo = "sha384";
            break;
        case "2.16.840.1.101.3.4.2.3":
            $algo = "sha512";
            $decryptedHash = getsignaturehash($decryptedSig);
            $certHash = hash($algo, $origCert);
            return $decryptedHash === $certHash;
            break;
        default:
            exit("Unknown signature hash algorithm oid: " . $oid);
    }
}
function pemToDer($pem = NULL)
{
    if(!is_string($pem)) {
        return false;
    }
    $cert_split = preg_split("/(-----((BEGIN)|(END)) CERTIFICATE-----)/", $pem);
    if(!isset($cert_split[1])) {
        return false;
    }
    return base64_decode($cert_split[1]);
}
function stripSignerAsn($der = NULL)
{
    if(!is_string($der) || strlen($der) < 8) {
        return false;
    }
    $bit = 4;
    $len = ord($der[$bit + 1]);
    $bytes = 0;
    if($len & 128) {
        $bytes = $len & 15;
        $len = 0;
        for ($i = 0; $i < $bytes; $i++) {
            $len = $len << 8 | ord($der[$bit + $i + 2]);
        }
    }
    return substr($der, 4, $len + 4);
}

?>